<template>
	<view :style="{ width: `${_width}rpx`, height: `${_height}rpx` }">
		<!-- #ifdef APP-NVUE -->
		<gcanvas
		v-if="show"
		 @mouseup.stop="touchend"
		 @mousedown.stop="touchstart"
		 @mousemove.stop="touchmove" 
		 @touchend.stop="touchend" 
		 @touchmove.stop="touchmove" 
		 @touchstart="touchstart" 
		 :id="canvasId" :ref="canvasId" class="canvas"
			:style="{ width: `${_width}rpx`, height: `${_height}rpx` }">
		</gcanvas>
		<!-- #endif -->
		<!-- #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ -->
		<canvas
		 @mouseup.stop="touchend"
		 @mousedown.stop="touchstart"
		 @mousemove.stop="touchmove" 
		 @touchend.stop="touchend" 
		 @touchmove.stop="touchmove" 
		 @touchstart.stop="touchstart" 
		 type="2d" id="canvasId" canvas-id="canvasId" class="canvas"
			:style="{ width: `${_width}rpx`, height: `${_height}rpx` }"></canvas>
		<!-- #endif -->
		<!-- #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ || APP-NVUE -->
		<canvas
		 @mouseup.stop="touchend"
		 @mousedown.stop="touchstart"
		 @mousemove.stop="touchmove" 
		 @touchend.stop="touchend" 
		 @touchmove.stop="touchmove" 
		 @touchstart.stop="touchstart" 
		 :id="canvasId" :canvas-id="canvasId" class="canvas"
			:style="{ width: `${_width}rpx`, height: `${_height}rpx` }"></canvas>
		<!-- #endif -->
	</view>
</template>

<script lang="ts" setup>
	/**
	 * 二维码
	 * @description 这是一个二维码组件，属性多，可以生成非常个性化的组件哦~
	 * 如果想知道生成的属性请查看：qrOpts类型属性。
	 * 更改任意属性，都将会导致重绘
	 */
	import {getCurrentInstance, computed, ref, onMounted,  nextTick } from 'vue';
	import crender from "./crender/index.js"
	import {tmCharts} from "./tmChart/tmChart"
	import type { CRenderTypes,CRenderGraph,GraphShapeTypes,CRenderGraphsConfig} from "./interface"
	import type { tmChartsType } from "./tmChart/interface"
	// #ifdef APP-NVUE
	import {
		enable,
		WeexBridge,
	} from '../../tool/gcanvas/index.js';
	const dom = uni.requireNativePlugin('dom')
	// #endif
	const { CRender,extendNewGraph,newGraph } = crender;
	const emits = defineEmits(["onInit","touchend","touchstart","touchmove"])
	const proxy = getCurrentInstance()?.proxy??null;
	const props = defineProps({
		width:{
			type:Number,
			default:750
		},
		height:{
			type:Number,
			default:500
		}
		
	})
	let render:CRenderTypes;
	const vnodeCtx = proxy
	const canvasId = ref("canvasId")
	const sysinfo = uni.getSystemInfoSync()
	const show = ref(true) //安卓上首次要隐藏不然卡。
	let isAndroid = false
	// #ifdef APP-NVUE
	isAndroid = uni.getSystemInfoSync().osName=='android'
	show.value = false
	// #endif
	
	let canvaConfig = {
		left:0,
		top:0,
		width:uni.upx2px(props.width),
		height:uni.upx2px(props.height)
	}
	// #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ
	canvasId.value = "tm" + uni.$tm.u.getUid(5);
	// #endif
	let ctx:UniApp.CanvasContext;
	let canvas2d:UniApp.CanvasContext;

	const _width = computed(()=>props.width)
	const _height = computed(()=>props.height)
	onMounted(()=>{
		// #ifdef APP-NVUE
		if(isAndroid){
			setTimeout(function() {
				show.value = true;
			}, 200);
		}else{
			show.value = true;
		}
		// #endif
	})

	
	function init():Promise<tmCharts|CRenderTypes>{
		return new Promise((res,rej)=>{
			if(render){
				res(render);
				return;
			}
			let delayTime = 150
			if(isAndroid){
				delayTime = 250
			}
			// #ifdef APP-VUE
			delayTime = 50
			// #endif
			
			setTimeout(async function () {
				// #ifdef APP-NVUE
				ctx = await drawNvue_init();
				
				// #endif
				// #ifdef MP-WEIXIN || MP-ALIPAY || MP-QQ
				const {ctx2d,canvas} = await MpWeix_init();
				ctx = ctx2d;
				canvas2d = canvas

				// #endif
				
				// #ifndef MP-WEIXIN || MP-ALIPAY || MP-QQ || APP-NVUE
				ctx = await appvueH5Other();
				// #endif
				ctx.width = uni.upx2px(_width.value)
				ctx.height = uni.upx2px(_height.value)
				ctx['dpr'] = Math.ceil(sysinfo.pixelRatio)
				render = new CRender(ctx, proxy, canvas2d)
				render.dpr = Math.ceil(sysinfo.pixelRatio)
			
				res(new tmCharts(render))
			}, delayTime)
		})
	}
	//appvue,h5,和其它平台。
	function appvueH5Other():Promise<UniApp.CanvasContext> {
		return  new Promise((resolve,reject)=>{
			let c2d = uni.createCanvasContext(canvasId.value, vnodeCtx);
			uni.createSelectorQuery().in(vnodeCtx)
			.select(".canvas").boundingClientRect((result)=>{
				canvaConfig.left = result?.left??0;
				canvaConfig.top = result?.top??0;
				c2d['dpr'] =sysinfo.pixelRatio
				resolve(c2d)
			}).exec()
		})
	}
	//支付宝和微信，QQ 支持2d渲染。
	function MpWeix_init():Promise<{ctx2d:UniApp.CanvasContext,canvas:HTMLCanvasElement|null}> {
		return new Promise((resolve,rej)=>{
			const query = uni.createSelectorQuery().in(vnodeCtx)
			// #ifdef MP-ALIPAY
			
			query.select('#canvasId').node().exec((res2) => {
			    const canvas = res2[0].node;
				canvaConfig.left =  res2[0].left;
				canvaConfig.top =  res2[0].top;
				let ctxvb:UniApp.CanvasContext = canvas.getContext('2d');
				
				resolve({ctx2d:ctxvb,canvas:canvas})
			})
			// #endif
			// #ifdef MP-WEIXIN || MP-QQ
			query.select('#canvasId')
				.fields({
					node: true,
					size: true,
					context:true
				})
				.exec((res) => {
					canvaConfig.left = res[0].left;
					canvaConfig.top = res[0].top;
					// #ifdef MP-WEIXIN
					let canvas:any = res[0]?.node
					let ctxvb:UniApp.CanvasContext = canvas.getContext('2d');
					const dpr = uni.getSystemInfoSync().pixelRatio
					canvas.width = res[0].width * dpr
					canvas.height = res[0].height * dpr
					ctxvb.scale(dpr, dpr)
					resolve({ctx2d:ctxvb,canvas:canvas})
					// #endif
					
					// #ifdef MP-QQ
					resolve({ctx2d:res[0].context,canvas:null})
					// #endif
			})
			// #endif
		})
	}
	function drawNvue_init():Promise<UniApp.CanvasContext> {
		return new Promise((resolve,reject)=>{
			/*获取元素引用*/
			var ganvas:any = vnodeCtx?.$refs[canvasId.value]??null;
			dom?.getComponentRect(ganvas, function(res:any) {
				canvaConfig.left = res?.size?.left??0
				canvaConfig.top = res?.size?.top??0
				/*通过元素引用获取canvas对象*/
				var canvasObj = enable(ganvas, {
					bridge: WeexBridge
				});
				let cx  = canvasObj.getContext('2d');
				resolve(cx)
			})
		})
		
	}
	function save():Promise<string> {
		return new Promise((su, fa) => {
			if (!ctx){
				uni.showToast({title:"初始化失败",icon:"none"})
				fa("初始化失败")
				return;
			}
			let size = 500;
			// #ifdef APP-NVUE
			uni.showLoading({title:'...'})
			// ctx.getImageData(0,0,props.width,props.height,function(res:imageData){
			// 	console.log(ArrayBufferToBase64(res.data).length)
			// 	fa(true)
			// 	uni.hideLoading()
			// })
			
			ctx.toTempFilePath(0,0,size,size,uni.upx2px(size),uni.upx2px(size),"png",1,function(res:any){
				uni.hideLoading()
				console.log(res.errMsg)
				if(res.errMsg=="canvasToTempFilePath:ok"){
					su(res.tempFilePath)
				}else{
					fa(res.errMsg)
				}
				
			})
			
			// #endif
			
			// #ifndef APP-NVUE
			
			uni.canvasToTempFilePath(
				{
					x: 0,
					y: 0,
					width:uni.upx2px(size),
					height: uni.upx2px(size),
					canvasId: canvasId.value,
					canvas:canvas2d,
					success: function(res) {
						// 在H5平台下，tempFilePath 为 base64
						su(res.tempFilePath);
					},
					fail: res => {
						fa(res);
					}
				},
				
			);
			
			// #endif
		});
	}

	
	// ---------------
	let dragGrpahId = ""
	let isDrag = false;
	let old_x=0
	let old_y=0
	function touchend(event:TouchEvent|MouseEvent) {
		let evx = 0;
		let evy = 0;
		//触摸
		if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
			evx = event.changedTouches[0]?.x??event.changedTouches[0]?.pageX
			evy = event.changedTouches[0].y??event.changedTouches[0]?.pageY
			//电脑端。
		} else {
			evx = event.pageX - canvaConfig.left
			evy = event.pageY - canvaConfig.top;
	
		}
	
		let x = evx;
		let y = evy;
		dragGrpahId = "";
		isDrag = false
		
		//在那个元素上离开的。
		let gps = render.graphs;
		let isClickGrpahs = gps.filter((el, index) => {
			if (el.name == 'text') {
				el.hoverRect = [x,y,el.textWidth,el.textHeight]
			}
			console.log(el.hoverCheck([x, y], el))
			return el.hoverCheck([x, y], el) || el.hoverCheckProcessor([x, y], el);
		});
	
		if (isClickGrpahs.length > 0) {
			let nowgap = isClickGrpahs[0];
			// 执行元素上绑定的事件。
			if (nowgap[event.type]) nowgap[event.type].call(nowgap, {
				x: x,
				y: y
			});
		}
		//触发画板的事件。
		emits('touchend', {
			x: x,
			y: y,
			isCheck:isClickGrpahs.length > 0
		})
	}
	function touchmove(event:TouchEvent|MouseEvent) {
		
		let evx = 0;
		let evy = 0;
		let isPc = false
		//触摸
		if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
			evx = event.changedTouches[0]?.x??event.changedTouches[0]?.pageX
			evy = event.changedTouches[0].y??event.changedTouches[0]?.pageY
			isPc = false
			//电脑端。
		} else {
	
			evx = event.pageX - canvaConfig.left
			evy = event.pageY - canvaConfig.top;
			isPc = true;
		}
	
		let movex = evx - old_x;
		let movey = evy - old_y;
		let x = evx;
		let y = evy;
		// 触发发画板的事件
		emits('touchmove', {
			x: x,
			y: y
		})
		if(isDrag==false) return;
		//在哪个元素移动的。
		let gps = render.graphs;
		let isClickGrpahs = gps.filter((el, index) => {
			return (el.hoverCheck([x, y], el) || el.hoverCheckProcessor([x, y], el))&&el.tmid==dragGrpahId;
		});
	
		if (isClickGrpahs.length > 0) {
			
			
			let nowgap = isClickGrpahs[0];
			if (isPc) {
				movex = evx -old_x;
				movey = evy - old_y;
			}
			if ((nowgap.drag === true && isDrag == true) || (nowgap.drag === true && isPc == false)) {
				
				if (nowgap.name == "circle" || nowgap.name == "ellipse" ||
					nowgap.name == "ring" || nowgap.name == "arc" || nowgap.name == "regPolygon") {
					nowgap.attr('shape', {
						rx: movex,
						ry: movey
					})
				} else if (nowgap.name == "rect" ||nowgap.name ==  'rectRound'|| nowgap.name == "path"|| nowgap.name == "image"|| nowgap.name == "star" || nowgap.name =='arrow') {
					nowgap.attr('shape', {
						x: movex,
						y: movey
					})
				} else if (nowgap.name == "text") {
					nowgap.attr('shape', {
						position: [movex, movey]
					})
				}
	
				// 执行元素上绑定的事件。
				if (nowgap[event.type]) nowgap[event.type].call(nowgap, {
					x: movex,
					y: movey
				});
				// if(nowgap['mousemove']||nowgap['touchmove']){
	
				// 	if (nowgap['mousemove']) nowgap.mousemove.call(nowgap,{x:movex,y:movey})
				// 	if (nowgap['touchmove']) nowgap.touchmove.call(nowgap,{x:movex,y:movey})
				// }
			}
			//配置不允许拖出边界。
			// if(this.dragGrpahId === nowgap.tmid 
			// && movex+nowgap.shape.w<this.canvaConfig.width
			// && movey+nowgap.shape.h<this.canvaConfig.height
			// && x>=0&&y>=0&&movex>=0&&movey>=0
			// ){
	
	
			// }
			// this.$emit('shape:touchmove',{x:x,y:y,shape:nowgap})
		}
	
	}
	function touchstart(event:TouchEvent|MouseEvent) {
		
		let evx = 0;
		let evy = 0;
		let isPc = false
		//触摸
		if (event.type.indexOf('mouse') == -1 && event.changedTouches.length == 1) {
			evx = event.changedTouches[0]?.x??event.changedTouches[0]?.pageX
			evy = event.changedTouches[0].y??event.changedTouches[0]?.pageY
			isPc = false
			//电脑端。
		} else {
			evx = event.pageX - canvaConfig.left
			evy = event.pageY - canvaConfig.top
			isPc = true;
		}
	
		let x = evx
		let y = evy
	
		let gps = render.graphs;
		//点中了哪些图片，第一个是最顶层的，依次类推。
		let isClickGrpahs = gps.filter((el, index) => {
			// 要判断谁的层级高就是先托动谁。
			return el.hoverCheck([x, y], el) || el.hoverCheckProcessor([x, y], el);
		});
		
		if (isClickGrpahs.length > 0) {
			var indexOfMax = 0;
			var max = isClickGrpahs.reduce( (a,c,i) => c.index > a ? (indexOfMax = i,c.index) : a, 0)
			let nowgap = isClickGrpahs[indexOfMax];
			
			if (nowgap.drag === true) {
				dragGrpahId = nowgap.tmid;
				let gapPos = [];
				if (nowgap.name == "circle" || nowgap.name == "ellipse" ||
					nowgap.name == "ring" || nowgap.name == "arc" || nowgap.name == "regPolygon"
					
				) {
					gapPos = [nowgap.shape.rx, nowgap.shape.ry]
				} else if (nowgap.name == "rect" ||nowgap.name ==  'rectRound'|| nowgap.name == "path"|| nowgap.name == "image"|| nowgap.name == "star"|| nowgap.name =='arrow') {
					gapPos = [nowgap.shape.x, nowgap.shape.y]
				} else if (nowgap.name == "text") {
					gapPos = nowgap.shape.position
				} 
				if (isPc) {
					old_x = evx - gapPos[0]
					old_y = evy - gapPos[1];
				} else {
					old_x = x - gapPos[0];
					old_y = y - gapPos[1];
				}
	
				isDrag = true
				
			}
			// 执行元素上绑定的事件。
			
			if (nowgap[event.type]) nowgap[event.type].call(nowgap, {
				x: x,
				y: y
			});
		} else {
			dragGrpahId = ""
		}
		
		emits('touchstart', {
			x: x,
			y: y
		})
	}
	

	//save保存当前渲染的图片,init重新初始化对象
	defineExpose({save,init:init})
</script>

<style>
</style>